package com.tcs.util.spring;

import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

/**
 * 动态添加 Spring IOC 容器的Bean
 * 
 * @Title: SpringIocUtils.java
 * @Package com.tcs.util.spring
 * @author 神经刀
 * @date 2018年8月9日
 * @version V1.0
 */
@Component(value="springIocUtils")
public final class SpringIocUtils {

	private SpringIocUtils() {};

	/**
	* @Title: setRegisterBean  
	* @Description: 注册Bean,默认为 PROTOTYPE.
	* @param clazz Bean
	 */
	public static void setRegisterBean(Class<?> clazz) {
		if (null == clazz) throw new NullPointerException("Class为null,请检查!");
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringConfigTool
				.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();
		BeanDefinitionBuilder beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		beanDefinition.setScope(SpringSpoceEnum.PROTOTYPE.getName());
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinition.getRawBeanDefinition());
	}
	
	/**
	* @Title: setRegisterBean  
	* @Description: 注册Bean
	* @param clazz Bean
	* @param SpringSpoceEnum    {@link SpringSpoceEnum} 注册类型
	 */
	public static void setRegisterBean(Class<?> clazz,SpringSpoceEnum springSpoceEnum) {
		if (null == clazz) throw new NullPointerException("Class为null,请检查!");
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringConfigTool
				.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();
		BeanDefinitionBuilder beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		beanDefinition.setScope(springSpoceEnum.getName());
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinition.getRawBeanDefinition());
	}

	/**
	* @Title: setRegisterBean  
	* @Description: 注册Bean,默认为 PROTOTYPE.
	* @param clazz Bean
	* @param paramsMap    参数  
	 */
	public static void setRegisterBean(Class<?> clazz, Map<String, Object> paramsMap) {
		if (null == paramsMap || paramsMap.isEmpty()) throw new NullPointerException("参数为空,请检查!");
		if (null == clazz) throw new NullPointerException("Class为null,请检查!");
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringConfigTool
				.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();
		BeanDefinitionBuilder beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
			beanDefinition.addPropertyValue(entry.getKey(), entry.getValue());
		}
		beanDefinition.setScope(SpringSpoceEnum.PROTOTYPE.getName());
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinition.getRawBeanDefinition());
	}
	
	/**
	* @Title: setRegisterBean  
	* @Description: 注册Bean,默认为 PROTOTYPE.
	* @param clazz Bean
	* @param paramsMap    参数
	* @param springSpoceEnum : {@link SpringSpoceEnum}
	 */
	public static void setRegisterBean(Class<?> clazz, Map<String, Object> paramsMap,SpringSpoceEnum springSpoceEnum) {
		if (null == paramsMap || paramsMap.isEmpty()) throw new NullPointerException("参数为空,请检查!");
		if (null == clazz) throw new NullPointerException("Class为null,请检查!");
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringConfigTool
				.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();
		BeanDefinitionBuilder beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
			beanDefinition.addPropertyValue(entry.getKey(), entry.getValue());
		}
		beanDefinition.setScope(springSpoceEnum.getName());
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinition.getRawBeanDefinition());
	}
	
	/**
	* @Title: setRegisterBean  
	* @Description: 注册Bean,默认为 PROTOTYPE.
	* @param clazz Bean
	* @param paramsMap    参数
	* @param springSpoceEnum : {@link SpringSpoceEnum}
	 */
	public static void setRegisterBean(Class<?> clazz, Map<String, Object> paramsMap , Map<String, Object> constructorMap ,SpringSpoceEnum springSpoceEnum) {
		if (null == clazz) throw new NullPointerException("Class为null,请检查!");
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringConfigTool
				.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();
		BeanDefinitionBuilder beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		if (MapUtils.isNotEmpty(paramsMap)) {
			for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
				beanDefinition.addPropertyValue(entry.getKey(), entry.getValue());
			}
		}
		if (MapUtils.isNotEmpty(constructorMap)) {
			for (Map.Entry<String, Object> entry : constructorMap.entrySet()) {
				beanDefinition.addConstructorArgValue(entry.getValue());
			}
		}
		beanDefinition.setScope(springSpoceEnum.getName());
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinition.getRawBeanDefinition());
	}
}